package net.pws.common.security.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.pws.common.security.PrincipalManagerFactory;
import net.pws.common.security.SecurityContext;
import net.pws.common.security.spi.Principal;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class LogoutProcessor extends AbstractAuthenticateFilter {
    
    public static final Log logger = LogFactory.getLog(LogoutProcessor.class);
    
    public static final String LOGOUT_PROCESS_URI = "/logout";
    
    private String logoutUrl = LOGOUT_PROCESS_URI;
    
    public String getLogoutUrl() {
        return logoutUrl;
    }
    
    public void setLogoutUrl(String logoutUrl) {
        this.logoutUrl = logoutUrl;
    }
    
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain chain) throws IOException,
                                           ServletException {
        if (!(request instanceof HttpServletRequest)) {
            throw new ServletException("Can only process HttpServletRequest");
        }
        
        if (!(response instanceof HttpServletResponse)) {
            throw new ServletException("Can only process HttpServletResponse");
        }
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        if (!required(httpRequest, httpResponse)) {
            chain.doFilter(request, response);
            return;
        }
        
        String token = determineAuthTokenValue(httpRequest);
        
        Principal auth = PrincipalManagerFactory.getInstance().get(token);
        
        if (logger.isDebugEnabled()) {
            logger.debug("Logging out user '" + auth
                         + "' and redirecting to "
                         + getLoginPage());
        }
        
        // clear cached-princpal
        PrincipalManagerFactory.getInstance().remove(token);
        // clear thread-binded-princpal
        SecurityContext.clear();
        // clear client-side-cookie
        removeTokenCookie(httpResponse);
        
        sendRedirect(httpRequest, httpResponse, getLoginPage());
    }
    
    public void removeTokenCookie(HttpServletResponse response) {
        response.addCookie(new Cookie(AUTH_TOKEN_KEY, null));
        response.addCookie(new Cookie("JSESSIONID", null));
    }
    
    protected boolean required(HttpServletRequest request,
                               HttpServletResponse response) {
        return matches(request, response, getLogoutUrl());
    }
    
}
